﻿
namespace Patterns4Net.Tests.PatternEnforcer.Core.Patterns.Regression
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using NUnit.Framework;
    using Patterns4Net.Core.CecilExtensions;
    using Patterns4Net.Core.Patterns;
    using Patterns4Net.PatternEnforcer.Core.Patterns;

    [TestFixture]
    public class CompositeCheckerTest : PatternCheckerTestBase
    {
        [Test]
        [TestCase(typeof(DoesNotContainComponents))]
        [TestCase(typeof(CorrectCompositeWithLoop))]
        [TestCase(typeof(CorrectCompositeWithLinq))]
        [TestCase(typeof(InCorrectCompositeWithoutLoop))]
        public void RunAllTest(Type type)
        {
            var checker = new CompositePatternChecker();
            this.TestChecker(checker, type, new Composite(type.GetTypeDefinition(), typeof(IComponent).GetTypeDefinition()));
        }

        public interface IComponent
        {
            int Number { get; }
        }

        [PatternTest(false)]
        public class DoesNotContainComponents : IComponent
        {
            public int Number
            {
                get { return 0; }
            }
        }

        [PatternTest(true)]
        public class CorrectCompositeWithLoop : IComponent
        {
            private readonly IEnumerable<IComponent> components;

            public CorrectCompositeWithLoop(IEnumerable<IComponent> components)
            {
                this.components = components;
            }

            public int Number
            {
                get
                {
                    int result = 0;
                    foreach (var component in this.components)
                    {
                        result += component.Number;
                    }

                    return result;
                }
            }
        }

        [PatternTest(true)]
        public class CorrectCompositeWithLinq : IComponent
        {
            private readonly IEnumerable<IComponent> components;

            public CorrectCompositeWithLinq(IEnumerable<IComponent> components)
            {
                this.components = components;
            }

            public int Number
            {
                get
                {
                    return this.components.Sum(c => c.Number);
                }
            }
        }

        [PatternTest(false)]
        public class InCorrectCompositeWithoutLoop : IComponent
        {
            private readonly IEnumerable<IComponent> components;

            public InCorrectCompositeWithoutLoop(IEnumerable<IComponent> components)
            {
                this.components = components;
            }

            public int Number
            {
                get { return 0; }
            }
        }
    }
}
